package base.reflecton;

import java.lang.reflect.Method;

import base.patterns.operation.Function;

public class ReflectionCall<Result, Param> implements Function<Result, Param> {

	private Object o;
	private Method method;
	
	public ReflectionCall(Object o, String methodName){
		this.o = o;
		this.method = ReflectionUtils.findMethod(o, new ReflectionUtils.MethodNameAnnotationPredicate(methodName));
		if (null == this.method){
			String errorMsg = String.format("C'ant init %s, " +
					"Object %s missing operation with Annotation DelegateSlot(name= '%s')",
					this.getClass().getSimpleName(),
					o.getClass().getSimpleName(), 
					methodName);
			throw new RuntimeException(errorMsg);
		}
	}
	
	@Override
	public Result call(Param par) {
		return invoke(new Object[] {par});
	}

	@Override
	public String toString() {
		return  ReflectionUtils.getMethodDesription(method);
	}
	
	private Result invoke(Object ... args){
		try {
			@SuppressWarnings("unchecked")
			Result res = (Result)method.invoke(o, args);
			return res;
		} catch (Exception e) {
			throw new RuntimeException("Can't invoke delegate method, with reason " + e.toString(), e);
		} 
	}
}
